package com.wlc.factory;

import com.wlc.pojo.MyBean;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.XPath;
import org.dom4j.io.SAXReader;

import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 王立朝
 * @description 实现BeanFactory
 * <p>
 * 模拟Spring实现：
 * 1.通过构造器获取相应的配置文件  类似于  ApplicationContext context = new ClassPathXmlApplicationContext("/spring/Spring.xml");
 * 2.通过dom4j解析xml文件  然后会得到一个List ,里面会存储所有的 对象的ID 和 class 属性
 * 3.通过反射实例化这些集合中的bean
 * 4.得到指定的bean对象
 * @date 2021-11-12 23:48:37
 */
public class MyApplicationContext implements MyBeanFactory {

    List<MyBean> myBeans;
    Map<String,Object> map = new HashMap<>();
    /**
     * 配置文件地址
     */
    private String filePath;

    public MyApplicationContext(String filePath) {
        //  2.通过dom4j解析xml文件  然后会得到一个List
        this.parseXml(filePath);
        // 4. 通过反射实例化这些集合中的bean
        this.instanceBean(myBeans);
    }

    private void instanceBean(List<MyBean> myBeans) {
        for (int i = 0; i < myBeans.size(); i++) {
            try {
                Object instance = Class.forName(myBeans.get(i).getClazz()).newInstance();
                map.put(myBeans.get(i).getId(),instance);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }


        }
    }

    private void parseXml(String filePath) {
        // 1.获取解析器
        SAXReader reader = new SAXReader();
        // 2.得到配置文件的url
        URL url = this.getClass().getClassLoader().getResource(filePath);
        try {
            // 3.通过解析器解析xml文件
            Document document = reader.read(url);
            // 4.通过xpath语法获取所有 beans/bean
            XPath xPath = document.createXPath("beans/bean");
            // 5.通过语法解析文档对象
            List<Element> list = xPath.selectNodes(document);
            myBeans = new ArrayList<>();
            for (Element e : list) {
                String id = e.attributeValue("id");
                String clazz = e.attributeValue("class");
                // 把 id和 class 放入list集合中
                myBeans.add(new MyBean(id, clazz));
            }

        } catch (DocumentException e) {
            e.printStackTrace();
        }

    }

    /**
     * 根据bean的ID获取到相应的对象bean
     *
     * @param id 要获取对象的ID
     * @return
     */
    @Override
    public Object getBean(String id) {
        return map.get(id);
    }
}
